using System;
using System.Collections.Generic;
using System.Text;

namespace BuildingBasicDomain
{
    public interface IGeometry
    {
        IPoint GetMiddle();

        //CoordinateSystem LocalCoordinateSystem{get ; set ;}
    }
    [Serializable]
    public class CoordinateSystem
    {

    }
    [Serializable]
    public abstract  class CoordinateSystem3D : CoordinateSystem 
    {

        public virtual IPoint TransformToCoordinateSystem(CoordinateSystem3D initialSystem, IPoint point) { return null; }

        public virtual ILine  TransformToCoordinateSystem(CoordinateSystem3D initialSystem, ILine line) { return null; }

        public virtual CommonTypes.Math.Vector3D TransformToCoordinateSystem(CoordinateSystem3D initialSystem, CommonTypes.Math.Vector3D vector) { return default(CommonTypes.Math.Vector3D); }


    }

    /// <summary>
    /// 
    /// </summary>
    [Serializable ]
    public   class CartesianCoordinateSystem3D : CoordinateSystem3D, ICloneable 
    {

        CommonTypes.Math.Vector3D center;

        public CommonTypes.Math.Vector3D Center
        {
            get { return center; }
            set { center = value; }
        }

        CommonTypes.Math.Vector3D axis1;

        public CommonTypes.Math.Vector3D Axis1
        {
            get { return axis1; }
            set { axis1 = value; }
        }

        CommonTypes.Math.Vector3D axis2;

        public CommonTypes.Math.Vector3D Axis2
        {
            get { return axis2; }
            set { axis2 = value; }
        }

        CommonTypes.Math.Vector3D axis3;

        public CommonTypes.Math.Vector3D Axis3
        {
            get { return axis3; }
            set { axis3 = value; }
        }

        public CartesianCoordinateSystem3D(CommonTypes.Math.Vector3D center,
         CommonTypes.Math.Vector3D Axis1,
         CommonTypes.Math.Vector3D Axis2,
         CommonTypes.Math.Vector3D Axis3)
        {
            this.center = center;
            this.axis1 = Axis1;
            this.axis2 = Axis2;

            this.axis3 = Axis3;
        }

        /// <summary>
        /// Rotate Coordinate System around its center 
        /// </summary>
        /// <param name="angles">Euler Angles  </param>
        public void RotateToItsCenter(CommonTypes.Math.Vector3D angles)
        {
            CommonTypes.Math.Matrix4F rotation = 
                CommonTypes.Math.Geometry3D.Transformation.GetRotationMatrix(angles);
            CommonTypes.Math.Vector4F vect4f = new CommonTypes.Math.Vector4F((float)Axis1.X, (float)Axis1.Y, (float)Axis1.Z, 1);
            CommonTypes.Math.Vector4F vect4fn = rotation * vect4f;
            Axis1 = new CommonTypes.Math.Vector3D(vect4fn.X, vect4fn.Y, vect4fn.Z);

            vect4f = new CommonTypes.Math.Vector4F((float)Axis2.X, (float)Axis2.Y, (float)Axis2.Z, 1);
            vect4fn = rotation * vect4f;
            Axis2 = new CommonTypes.Math.Vector3D(vect4fn.X, vect4fn.Y, vect4fn.Z);
            vect4f = new CommonTypes.Math.Vector4F((float)Axis3.X, (float)Axis3.Y, (float)Axis3.Z, 1);
            vect4fn = rotation * vect4f;
            Axis3 = new CommonTypes.Math.Vector3D(vect4fn.X, vect4fn.Y, vect4fn.Z);

        }

        /// <summary>
        /// Moves Coordinate system  center 
        /// </summary>
        /// <param name="vector">Transport of Center </param>
        /// 
        public void Transfer(CommonTypes .Math .Vector3D vector )
        {
            this.Center = Center + vector;
        }

        /// <summary>
        /// Gets the new coordinate System. when the referance system rotates around its 
        /// center the specified angles 
        /// </summary>
        /// <param name="referanceCoordinateSystem">The Referance Global Coordinate System</param>
        /// <param name="angles">angles of rotation of referanceCoordinateSystem system </param>
        public void RotateToReferanceCoordinateSystem(CartesianCoordinateSystem3D referanceCoordinateSystem, CommonTypes.Math.Vector3D angles)
        {
    

        }

        public void GetTransformation(CartesianCoordinateSystem3D referanceCoordinateSystem, out CommonTypes.Math.Vector3D angles ,out  CommonTypes.Math.Vector3D transport) 
        {
            angles = default(CommonTypes.Math.Vector3D);
            transport = default(CommonTypes.Math.Vector3D);

            angles.Y =CommonTypes .Geometry .RadToDeg ( Math.Acos(CommonTypes .Math .Vector3D .DotProduct ( this.Axis3 ,referanceCoordinateSystem .Axis3)));

         //   IPoint point = (Point)(CommonTypes.Math.Vector3D)Axis3;
        //    CommonTypes.Math.Geometry3D.Plane planexy =referanceCoordinateSystem. Get12Plane();
          //  Area area = new Area(); area.Plane = planexy;
         //   ILine line = new Line((Point)center,(Point) this .Axis1 );
         //   ILine lineProjected = area.projectedLine(line);
         //   lineProjected.Direction.Normalize();
         //   angles.X = CommonTypes.Geometry.RadToDeg(Math.Acos(CommonTypes.Math.Vector3D.DotProduct(referanceCoordinateSystem.Axis1, lineProjected.Direction)));
            

           



          //  angles.Z = CommonTypes.Geometry.RadToDeg(Math.Acos(CommonTypes.Math.Vector3D.DotProduct(this.Axis3, referanceCoordinateSystem.Axis1)));

        }

        public CommonTypes.Math.Geometry3D.Plane Get12Plane()
        {
            CommonTypes.Math.Geometry3D.Plane plane = new CommonTypes.Math.Geometry3D.Plane(
                (( CommonTypes.Math.Vector3F)Axis3) , 
                ((CommonTypes.Math.Vector3F)Center));
            return plane;
        }
        public CommonTypes.Math.Geometry3D.Plane Get13Plane()
        {
            CommonTypes.Math.Geometry3D.Plane plane = new CommonTypes.Math.Geometry3D.Plane(( CommonTypes.Math.Vector3F)Axis2, ((CommonTypes.Math.Vector3F)Center));
            return plane;
        }
        public CommonTypes.Math.Geometry3D.Plane Get23Plane()
        {
            CommonTypes.Math.Geometry3D.Plane plane = new CommonTypes.Math.Geometry3D.Plane((CommonTypes.Math.Vector3F)Axis1, ((CommonTypes.Math.Vector3F)Center));
            return plane;
        }


        public CommonTypes.Math.Matrix3D GetDirectionCosineMatrix(CartesianCoordinateSystem3D referanceCoordinateSystem)
        {
          //  return default ( CommonTypes .Math .Matrix4D );

            return CommonTypes.Math.Matrix3D.InnerMultiply(this.GetDirectionCosineMatrix(), referanceCoordinateSystem.GetDirectionCosineMatrix());
      
        }

        public CommonTypes.Math.Matrix3D GetDirectionCosineMatrix()
        {
            return new CommonTypes.Math.Matrix3D(Axis1.X, Axis2.X, Axis3.X, Axis1.Y, Axis2.Y,
                  Axis3.Y, Axis1.Z, Axis2.Z, Axis3.Z);
        }


        #region ICloneable Members

        public object Clone()
        {
            CartesianCoordinateSystem3D newSystem = new CartesianCoordinateSystem3D(this.center.Clone(), this.axis1.Clone(), this.axis2.Clone(), this.axis3.Clone());
            return newSystem;
        }

        #endregion
    }

    public class CoordinateSystem2D : CoordinateSystem
    {

    }

}
